package com.ylr.base.common.utils;

import com.ylr.base.common.enums.ResultEnum;
import com.ylr.base.common.exception.YlrException;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.nio.charset.StandardCharsets;
import java.util.Objects;
import java.util.regex.Pattern;

/**
 * Created by IntelliJ IDEA.
 *
 * @author wyw
 * date: 2023-09-04 10:24:29
 * className: ByteUtils 字节操作工具类
 * version: 1.0
 * description:
 */

public class ByteUtils {

    private static final Logger log = LoggerFactory.getLogger(ByteUtils.class);

    /**
     * 将字节数组转换成十六进制值
     * @param plainText 待转换的字节数组
     * @return 转换完成的十六进制数字
     */
    public static String bytesToHex(byte[] plainText) {
        if (Objects.isNull(plainText)) {
            log.error("字节数组转十六进制值参数为空");
            throw new YlrException(ResultEnum.SERVICE_FAIL);
        }
        return doBytesToHex(plainText, false);
    }

    /**
     * 将字节数组转换成十六进制值
     * @param plainText 待转换的字节数组
     * @param toUpper   十六进制值大写
     * @return 转换完成的十六进制数字
     */
    public static String bytesToHex(byte[] plainText, boolean toUpper) {
        if (Objects.isNull(plainText)) {
            log.error("字节数组转十六进制值参数为空");
            throw new YlrException(ResultEnum.SERVICE_FAIL);
        }
        return doBytesToHex(plainText, toUpper);
    }

    /**
     * 将十六进制值转换成字节数组
     * @param cipherText 十六进制值
     * @return 字节数组
     */
    public static byte[] hexToBytes(String cipherText) {
        if (StringUtils.isBlank(cipherText)) {
            log.error("十六进制值转字节数组参数为空");
            throw new YlrException(ResultEnum.SERVICE_FAIL);
        }
        if (!Pattern.matches("[0-9a-fA-F]+", cipherText)) {
            log.error("十六进制数值格式错误。cipherText={}", cipherText);
            throw new YlrException(ResultEnum.SERVICE_FAIL);
        }
        char[] valueArray = cipherText.toCharArray();
        byte[] result = new byte[cipherText.length() / 2];

        int n, index = 0, length = result.length;
        for (int i = 0; i < length; i++) {
            n = changeValue(valueArray[index++]) * 16;
            n += changeValue(valueArray[index++]);
            result[i] = (byte) (n & 0xFF);
        }
        return result;
    }

    /**
     * 将字节数组转换成十六进制数字
     * @param plainText 待转换的字节数组
     * @param toUpper   十六进制数字大写
     * @return 转换完成的十六进制数字
     */
    private static String doBytesToHex(byte[] plainText, boolean toUpper) {
        // 结果缓存数组
        char[] result = new char[plainText.length * 2];

        char[] hexArray;
        if (toUpper) {
            hexArray = new char[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
        } else {
            hexArray = new char[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
        }
        int index = 0;
        for (byte b : plainText) {
//            int hexIndex = (b & 0x0f0) >> 4;
//            result[index++] = hexArray[hexIndex];
//            hexIndex = b & 0x0f;
//            result[index++] = hexArray[hexIndex];
            result[index++] = hexArray[b >>> 4 & 15];
            result[index++] = hexArray[b & 15];
        }
        return new String(result);
    }

    /**
     * 十六进制字符值转化成十进制数值
     * @param value 十六进制字符值
     * @return 十进制数值
     */
    private static int changeValue(int value) {
        // 计算得到字符a-f对应的值
        int result = value % 97 + 10;
        if (result > 15) {
            // 计算得到字符A-F对应的值
            result = value % 65 + 10;
            if (value > 15) {
                // 计算得到字符0-9对应的值
                result = value % 48;
            }
        }
        return result;
    }

    public static void main(String[] args) {

        String value = "abc123";

        String hex = ByteUtils.bytesToHex(value.getBytes(StandardCharsets.UTF_8));
        System.out.println("hex = " + hex);
        value = new String(ByteUtils.hexToBytes(hex));
        System.out.println("value = " + value);

    }

}
